package cn.dyn.funchat.netty.server.handler;

import cn.dyn.funchat.pojo.bo.UserBO;
import cn.dyn.funchat.utils.ChannelContextUtil;
import cn.dyn.funchat.utils.TraceIdUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@Slf4j
public class WebsocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private final ChannelContextUtil channelContextUtil;

    public WebsocketHandler() {
        this.channelContextUtil = SpringUtil.getBean(ChannelContextUtil.class);
    }

    /**
     * 读取消息
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
        Channel channel = ctx.channel();
        String text = textWebSocketFrame.text();
        if ("PING".equals(text)) {
            channel.writeAndFlush(new TextWebSocketFrame("PONG"));
        }
        Attribute<Long> attributeUserIdKey = channel.attr(AttributeKey.valueOf(channel.id().toString()));
        Long userId = attributeUserIdKey.get();
        log.info("收到用户id：{} 的消息：{}", userId, text);
    }

    /**
     * 通道就绪后，调用，一般用来做初始化，但是很多信息都拿不到
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        TraceIdUtil.putTraceId();
        log.info("有新的连接加入");
    }

    /**
     * 有连接断开
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("有连接断开");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            WebSocketServerProtocolHandler.HandshakeComplete complete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
            log.info("握手成功：{}", complete);
            HttpHeaders headers = complete.requestHeaders();
            log.info("请求头：{}", JSONObject.toJSONString(headers));
            String uri = complete.requestUri();
            log.info("请求uri：{}", uri);
            String token = getToken(uri);
            if (!StringUtils.hasText(token)) {
                ctx.channel().close();
                return;
            }
            // TODO 从redis 中获取用户信息；
            UserBO user = queryUserInfo(token);
            if (user == null) {
                ctx.channel().close();
                return;
            }
            channelContextUtil.addContext(user.getUserId(), ctx.channel());
        }
    }

    private String getToken(String uri) {
        if (!StringUtils.hasText(uri) && !uri.contains("?")) {
            return null;
        }
        // 提取 Query String 部分（"abc=xxx&def=xxx"）
        String queryString = uri.substring(uri.indexOf("?") + 1);

        // 解析成 Map
        Map<String, String> paramMap = HttpUtil.decodeParamMap(queryString, StandardCharsets.UTF_8);
        String token = paramMap.get("token");
        log.info("token: {}", token);
        return token;
    }

    private void test() {
        RedisTemplate bean = SpringUtil.getBean(RedisTemplate.class);

    }

    private UserBO queryUserInfo(String token) {
        // TODO 根据token获取用户信息
        boolean flag = true;
        if (flag) {
            return UserBO.genTest();
        }
        return null;
    }
}
